package com.zaofan.utils;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * Created by chenyan on 16/7/7.
 */
public class HTTPClient {

    private static final Logger logger = LoggerFactory.getLogger(HTTPClient.class);

    private static final int SOCKET_TIMEOUT = 6000;
    private static final int CONNECT_TIMEOUT = 3000;
    private static final String DEFAULT_CHARSET = "UTF-8";

    /**
     *
     * @return null if error
     */
    public static String postJson(String url, String content) {
        long startTime = System.currentTimeMillis();
        String result = null;

        HttpPost post = new HttpPost(url);
        post.setHeader("traceId", MDC.get("traceId") == null ? UUID.randomUUID().toString() : MDC.get("traceId"));
        post.setConfig(RequestConfig.custom()
                .setConnectTimeout(CONNECT_TIMEOUT)
                .setSocketTimeout(SOCKET_TIMEOUT)
                .build()
        );
        post.setEntity(new StringEntity(content, ContentType.create("application/json", DEFAULT_CHARSET)));
        HttpEntity entity = null;
        try {
            CloseableHttpResponse response = HttpClientBuilder.create().build().execute(post);
            entity = response.getEntity();
            if (entity != null) {
                result = EntityUtils.toString(entity, DEFAULT_CHARSET);
            }
        } catch (Exception e) {
            logger.error("http 远程调用异常, url: {}, params: {}", url, content, e);
        } finally {
            EntityUtils.consumeQuietly(entity);
        }
        logger.info("http 远程调用, url: {}, params: {}, result: {}, 耗时: {}ms", url, content, result, System.currentTimeMillis() - startTime);
        return result;
    }


    /**
     * 
     * @return null if error
     */
    public static String postMap(String url, Map<String, String> paramsMap) {
        List<NameValuePair> nameValuePairList = new ArrayList<NameValuePair>();
        if (paramsMap != null) {
            for (String key : paramsMap.keySet()) {
                nameValuePairList.add(new BasicNameValuePair(key, paramsMap.get(key)));
            }
        }
        return postEncodedForm(url, nameValuePairList);
    }

    private static String postEncodedForm(String url, List<NameValuePair> nameValuePairList) {
        long startTime = System.currentTimeMillis();
        String result = null;

        HttpPost post = new HttpPost(url);
        post.setHeader("traceId", MDC.get("traceId") == null ? UUID.randomUUID().toString() : MDC.get("traceId"));
        post.setConfig(RequestConfig.custom()
                .setConnectTimeout(CONNECT_TIMEOUT)
                .setSocketTimeout(SOCKET_TIMEOUT)
                .build()
        );
        HttpEntity entity = null;
        try {
            post.setEntity(new UrlEncodedFormEntity(nameValuePairList, DEFAULT_CHARSET));
            CloseableHttpResponse response = HttpClientBuilder.create().build().execute(post);
            entity = response.getEntity();
            if (entity != null) {
                result = EntityUtils.toString(entity, DEFAULT_CHARSET);
            }
        } catch (Exception e) {
            logger.error("http 远程调用异常, url: {}, params: {}", url, nameValuePairList, e);
        } finally {
            EntityUtils.consumeQuietly(entity);
            logger.info("http 远程调用, url: {}, params: {}, result: {}, 耗时: {}ms", url, nameValuePairList, result, System.currentTimeMillis() - startTime);
        }
        return result;
    }
}
